﻿using System;
using System.Collections.Generic;
using System.Linq;
using DeepZoomPivotConstructor.PivotLib;
using HtmlAgilityPack;
using PivotPhysicsPlotsGenerator.Utilities;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;

namespace PivotPhysicsPlotsGenerator.ATLAS
{
    static class ATLASUtilities
    {
        /// <summary>
        /// parses the master conf note page and returns a list of guys for everything else.
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        public static IEnumerable<PivotImage> ParseMasterCONFNOTENpage(Uri page)
        {
            HtmlWeb web = new HtmlWeb();
            var doc = web.Load(page.ToString());

            var allConfNotes = doc.DocumentNode.SelectNodes("//a");
            var pages = new EnumerableWrapper<HtmlNode>(allConfNotes).SelectMany(node =>
            {
                var hrefAttr = node.Attributes["href"];
                if (hrefAttr != null)
                {
                    Uri confPage = new Uri(page, hrefAttr.Value);
                    return ParseATLASCONFNotePage(confPage);
                }
                else
                {
                    return Enumerable.Empty<PivotImage>();
                }
            }
            );
            return pages;
        }

        /// <summary>
        /// Parse a standard ATLAS twiki page for plots
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        private static IEnumerable<PivotImage> ParseATLASCONFNotePage(Uri page)
        {
            HtmlWeb web = new HtmlWeb();
            var doc = web.Load(page.ToString());

            ///
            /// Find the tables that contain the actual text...
            /// 

            var allTables = doc.DocumentNode.SelectNodes("//table");
            var p = new ParseTableForImages(page);
            var images = new EnumerableWrapper<HtmlNode>(allTables).SelectMany(p.Process);

            ///
            /// Grab the info page and attach that here now
            /// 

            var info = ParseInfoPage(new Uri(page, page.Segments.Last().RemoveTrailing("/") + ".info"));
            var imagesWithInfo = images
                .Apply(i => i.Add("Date", (DateTime)info["DATE"]))
                .Apply(i => i.Add("Note Title", (string)info["TITLE"]))
                .Apply(i => i.Add("Experiment", "ATLAS"))
                .Apply(i => i.Add("More Information", "Note Page", page));


            ///
            /// Add the ATLAS experiment catagory to this thing
            /// 

            return imagesWithInfo;
        }
        
        /// <summary>
        /// Parse the ATLAS info web page to get things like date and title
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        public static Dictionary<string, object> ParseInfoPage(Uri uri)
        {
            var result = new Dictionary<string, object>();

            WebRequest meta = WebRequest.Create(uri);
            using (var resp = meta.GetResponse())
            {
                using (var outStream = new StreamReader(resp.GetResponseStream()))
                {
                    Regex rg = new Regex("<([^>]+)>");
                    do
                    {
                        string line = outStream.ReadLine();
                        var match = rg.Match(line);
                        if (match.Success)
                        {
                            line = outStream.ReadLine();
                            result[match.Groups[1].Value] = line;
                        }
                    } while (!outStream.EndOfStream);
                    outStream.Close();
                }
            }

            ///
            /// Fix up the date
            /// 

            if (result.ContainsKey("DATE"))
            {
                Regex dt = new Regex("([^-]+)-([^-]+)-([^-]+)");
                var fdate = dt.Match((string)result["DATE"]);
                if (fdate.Success)
                {
                    result["DATE"] = new DateTime(
                        Convert.ToInt32(fdate.Groups[3].Value),
                        Convert.ToInt32(fdate.Groups[2].Value),
                        Convert.ToInt32(fdate.Groups[1].Value)
                        );
                }
                else
                {
                    try
                    {
                        result["DATE"] = Convert.ToDateTime((string)result["DATE"]);
                    }
                    catch
                    {
                        result["DATE"] = DateTime.Now;
                    }
                }
            }

            return result;
        }
    }
}
